package com.lions.client.model;

import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.user.client.ui.Image;

/**
 * The data representing the module.
 * 
 * @author Brad
 * 
 */
public class Module implements Comparable<Module> {

	/**
	 * Random Module constructor. Constructs Module with given Type and Random X
	 * and Y values.
	 */
	public Module(int num) {
		this.manhattanDistanceToBase = 0;
		int random = new Double(Math.random()).intValue() % 10;
		if (random == 1) {
			this.type = Type.AIRLOCK;
		} else if (random == 2) {
			this.type = Type.CANTEEN;
		} else if (random == 3) {
			this.type = Type.CONTROL;
		} else if (random == 4) {
			this.type = Type.DORMITORY;
		} else if (random == 5) {
			this.type = Type.FOOD_WATER_STORAGE;
		} else if (random == 6) {
			this.type = Type.GYM;
		} else if (random == 7) {
			this.type = Type.MEDICAL;
		} else if (random == 8) {
			this.type = Type.PLAIN;
		} else if (random == 9) {
			this.type = Type.SANITATION;
		} else {
			this.type = Type.PLAIN;
		}
		this.condition = Condition.USABLE;
		this.turns = 0;
		this.code = (int) (Math.random() * 100);
		x = (int) (Math.random() * 100);
		y = (int) (Math.random() * 50);
	}

	/**
	 * Not a deep copy constructor, but a copy constructor nonetheless.
	 * @param m module
	 */
	public Module(final Module m) {
		this.manhattanDistanceToBase = 0;
		this.type = m.getType();
		this.condition = m.getCondition();
		this.turns = m.getTurns();
		this.code = m.getCode();
		this.x = m.getX();
		this.y = m.getY();
	}

	/**
	 * This is a deep copy constructor.
	 * @param type
	 * @param condition
	 * @param code
	 * @param turns
	 * @param xCoord
	 * @param yCoord
	 * @param collected
	 */
	public Module(final Type type, Condition condition, final int code,
			final int turns, final int xCoord, final int yCoord,
			boolean collected) {
		this.manhattanDistanceToBase = 0;
		this.type = type;
		this.condition = condition;
		this.turns = turns;
		this.code = code;
		this.x = xCoord;
		this.y = yCoord;
	}

	/**
	 * Creates a module from a string in the format of
	 * AIRLOCK|USABLE|0|5|5|5
	 * @param s the String representing the new module
	 */
	public Module(String s) {
		// Set type
		this.manhattanDistanceToBase = 0;
		int ZERO = 0;
		int index = s.indexOf("|");
		if (s.substring(ZERO, index).equals(Type.AIRLOCK.toString())) {
			this.type = Type.AIRLOCK;
		} else if (s.substring(ZERO, index).equals(Type.CANTEEN.toString())) {
			this.type = Type.CANTEEN;
		} else if (s.substring(ZERO, index).equals(Type.CONTROL.toString())) {
			this.type = Type.CONTROL;
		} else if (s.substring(ZERO, index).equals(Type.DORMITORY.toString())) {
			this.type = Type.DORMITORY;
		} else if (s.substring(ZERO, index).equals(
				Type.FOOD_WATER_STORAGE.toString())) {
			this.type = Type.FOOD_WATER_STORAGE;
		} else if (s.substring(ZERO, index).equals(Type.GYM.toString())) {
			this.type = Type.GYM;
		} else if (s.substring(ZERO, index).equals(Type.MEDICAL.toString())) {
			this.type = Type.MEDICAL;
		} else if (s.substring(ZERO, index).equals(Type.PLAIN.toString())) {
			this.type = Type.PLAIN;
		} else if (s.substring(ZERO, index).equals(Type.POWER.toString())) {
			this.type = Type.POWER;
		} else if (s.substring(ZERO, index).equals(Type.SANITATION.toString())) {
			this.type = Type.SANITATION;
		} else {
			this.type = Type.PLAIN;
		}

		// Set status
		s = s.substring(s.indexOf("|") + 1);
		index = s.indexOf("|");
		if (s.substring(ZERO, index).equals(Condition.REPAIRABLE.toString())) {
			this.condition = Condition.REPAIRABLE;
		} else if (s.substring(ZERO, index).equals(
				Condition.UNREPAIRABLE.toString())) {
			this.condition = Condition.UNREPAIRABLE;
		} else if (s.substring(ZERO, index).equals(Condition.USABLE.toString())) {
			this.condition = Condition.USABLE;
		} else {
			this.condition = Condition.USABLE;
		}

		// Set turns
		s = s.substring(s.indexOf("|") + 1);
		index = s.indexOf("|");
		int modTurns = Integer.parseInt(s.substring(ZERO, index));
		if ((modTurns > 3) && (modTurns < 0)) {
			this.turns = modTurns;
		} else {
			this.turns = 0;
		}

		// Set code
		s = s.substring(s.indexOf("|") + 1);
		index = s.indexOf("|");
		int modCode = Integer.parseInt(s.substring(ZERO, index));
		if ((modCode < 190) && (modCode > 0)) {
			this.code = modCode;
		} else {
			this.code = 0;
		}

		// Set X
		s = s.substring(s.indexOf("|") + 1);
		index = s.indexOf("|");
		int xval = Integer.parseInt(s.substring(ZERO, index));
		if ((xval < 101) && (xval > 0)) {
			this.x = xval;
		} else {
			this.x = 0;
		}

		// Set Y
		s = s.substring(index + 1);
		int yval = Integer.parseInt(s);
		if ((yval < 51) && (yval > 0)) {
			this.y = yval;
		} else {
			this.y = 0;
		}

	}

	/**
	 * Getter for the type of the specific module
	 * 
	 * @return ENUM Type
	 */
	public Type getType() {
		return type;
	}

	public int getTypeAsInt() {
		int num = -1;
		if (this.type == Type.AIRLOCK) {
			num = 0;
		} else if (this.type == Type.CANTEEN) {
			num = 1;
		} else if (this.type == Type.CONTROL) {
			num = 2;
		} else if (this.type == Type.DORMITORY) {
			num = 3;
		} else if (this.type == Type.FOOD_WATER_STORAGE) {
			num = 4;
		} else if (this.type == Type.GYM) {
			num = 5;
		} else if (this.type == Type.MEDICAL) {
			num = 6;
		} else if (this.type == Type.PLAIN) {
			num = 7;
		} else if (this.type == Type.POWER) {
			num = 8;
		} else if (this.type == Type.SANITATION) {
			num = 9;
		}
		return num;
	}

	/**
	 * Setter for the specific module
	 * 
	 * @param type
	 *            ENUM Type
	 */
	public void setType(final Type type) {
		this.type = type;
	}

	/**
	 * Getter for the condition of the specific module.
	 * 
	 * @return condition ENUM Condition
	 */
	public Condition getCondition() {
		return condition;
	}

	public int getConditionAsInt() {
		int num = -1;
		if (this.condition == Condition.USABLE) {
			num = 0;
		} else if (this.condition == Condition.REPAIRABLE) {
			num = 1;
		} else if (this.condition == Condition.UNREPAIRABLE) {
			num = 2;
		}
		return num;
	}

	/**
	 * Setter for the condition of this specific module
	 * 
	 * @param condition
	 *            ENUM Condition
	 */
	public void setCondition(Condition condition) {
		this.condition = condition;
	}

	/**
	 * Gets the number of turns for this module to be upright
	 * 
	 * @return integer turns
	 */
	public int getTurns() {
		return turns;
	}

	/**
	 * Setter for the number of turns to make this module upright
	 * 
	 * @param integer
	 *            turns
	 */
	public void setTurns(int turns) {
		this.turns = turns;
	}

	/**
	 * The module type code for this specific module
	 * 
	 * @return integer code
	 */
	public int getCode() {
		return code;
	}

	/**
	 * Setter for the module code number
	 * 
	 * @param integer
	 *            code
	 */
	public void setCode(int code) {
		this.code = code;
	}

	/**
	 * Getter for the x-coordinate of the module.
	 * 
	 * @return integer X
	 */
	public int getX() {
		return x;
	}

	/**
	 * Setter for the x-coordinate of the module
	 * 
	 * @param integer
	 *            x
	 */
	public void setX(int x) {
		this.x = x;
	}

	/**
	 * Getter for the y-coordinate of the module
	 * 
	 * @return integer Y
	 */
	public int getY() {
		return y;
	}

	/**
	 * Setter for the y-coordinate of the module
	 * 
	 * @param y
	 *            integer y
	 */
	public void setY(int y) {
		this.y = y;
	}

	/**
	 * Retuns the particular image that represents this module
	 * 
	 * @return ImageElement .jpg
	 */
	public ImageElement getImage() {
		Image img;
		ImageElement module;

		switch (type) {
		case AIRLOCK:
			img = new Image("images/Airlock.jpg");
			module = ImageElement.as(img.getElement());
		case CONTROL:
			img = new Image("images/Control.jpg");
			module = ImageElement.as(img.getElement());
		case POWER:
			img = new Image("images/Power.jpg");
			module = ImageElement.as(img.getElement());
			System.out.println("power");
		case FOOD_WATER_STORAGE:
			img = new Image("images/Food.jpg");
			module = ImageElement.as(img.getElement());
		case DORMITORY:
			img = new Image("images/Dormitory.jpg");
			module = ImageElement.as(img.getElement());
		case CANTEEN:
			img = new Image("images/Canteen.jpg");
			module = ImageElement.as(img.getElement());
		case SANITATION:
			img = new Image("images/Sanitation.jpg");
			module = ImageElement.as(img.getElement());
		case GYM:
			img = new Image("images/Airlock.jpg");
			module = ImageElement.as(img.getElement());
		case MEDICAL:
			img = new Image("images/Medical.jpg");
			module = ImageElement.as(img.getElement());
		case PLAIN:
			img = new Image("images/Plain.jpg");
			module = ImageElement.as(img.getElement());
		default:
			img = new Image("images/MarsImage.jpg");
			module = ImageElement.as(img.getElement());

		}
		return module;
	}

	/**
	 * The to string for this module. This is used for saving to HTML5 session
	 * storage AIRLOCK|USABLE|0|5|5|5|false
	 */
	@Override
	public String toString() {
		String modString = new String();
		String t = new String();
		String cond = new String();

		if (this.type.equals(Type.AIRLOCK)) {
			t = "AIRLOCK";
		} else if (this.type.equals(Type.CANTEEN)) {
			t = "CANTEEN";
		} else if (this.type.equals(Type.CONTROL)) {
			t = "CONTROL";
		} else if (this.type.equals(Type.DORMITORY)) {
			t = "DORMITORY";
		} else if (this.type.equals(Type.FOOD_WATER_STORAGE)) {
			t = "FOOD_WATER_STORAGE";
		} else if (this.type.equals(Type.GYM)) {
			t = "GYM";
		} else if (this.type.equals(Type.MEDICAL)) {
			t = "MEDICAL";
		} else if (this.type.equals(Type.PLAIN)) {
			t = "PLAIN";
		} else if (this.type.equals(Type.POWER)) {
			t = "POWER";
		} else if (this.type.equals(Type.SANITATION)) {
			t = "SANITATION";
		}

		if (this.condition.equals(Condition.REPAIRABLE)) {
			cond = "REPAIRABLE";
		} else if (this.condition.equals(Condition.UNREPAIRABLE)) {
			cond = "UNREPAIRABLE";
		} else {
			cond = "USABLE";
		}

		modString = t + "|" + cond + "|" + new Integer(this.turns).toString()
				+ "|" + new Integer(this.code).toString() + "|"
				+ new Integer(this.x).toString() + "|"
				+ new Integer(this.y).toString();
		return modString;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#equals(java.lang.Object) This equals does not
	 * contain the field "collected" Use this to see if a module is a duplicate
	 * to one marked collected.
	 * 
	 * @return true if other is a duplicate module.
	 */
	@Override
	public boolean equals(Object other) {
		Module module = (Module) other;

		return (this.type == module.getType()
				&& this.condition == module.getCondition()
				&& this.turns == module.getTurns()
				&& this.code == module.getCode() && this.x == module.getX() && this.y == module.y);
	}

	/**
	 * Returns the Modules known manhattanDistanceToBase.
	 * 
	 * @return this modules entered manhattanDistanceToBase
	 */
	public int getManhattanDistanceToBase() {
		return manhattanDistanceToBase;
	}

	/**
	 * Sets this Module's known manhattanDistanceToBase.
	 * 
	 * @param distance
	 *            This Modules known Manhattan Distance to the given base.
	 */
	public void setManhattanDistanceToBase(int distance) {
		manhattanDistanceToBase = distance;
	}

	/**
	 * Compare
	 * @param o module
	 */
	@Override
	public int compareTo(Module o) {
		return manhattanDistanceToBase
				.compareTo(o.getManhattanDistanceToBase());
	}

	private Type type;
	/**
	 * Condition.
	 */
	private Condition condition;
	/**
	 * Turns.
	 */
	private int turns;
	/**
	 * Code.
	 */
	private int code;
	/**
	 * x.
	 */
	private int x;
	/**
	 * y.
	 */
	private int y;
	/**
	 * manhattan.
	 */
	private Integer manhattanDistanceToBase;

}
